package irio.pythcal;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;

public class Shape {

	Paint paintLine = new Paint();
	Paint paintCorner = new Paint();
	Paint paintText = new Paint();
	Paint paintSideText = new Paint();
	Paint paintAngleText = new Paint();
	Paint paintArc = new Paint();

	
	
	
	
	private ArrayList<Particle> pList = new ArrayList<Particle>();
	private ArrayList<Float> pSides = new ArrayList<Float>();
	
	public Shape() {
		setupPaints();
	}

	public ArrayList<Particle> getList() {
		return pList;
	}
	
	public void createShape( int N ) {
		pList.clear();
		pSides.clear();
		PythCal.cont.visualScale = 1.0f;
		for (int i=0;i<N;i++) {
			Complex c = Complex.polar(1.0f,(2.0f*Math.PI/(float)N)*i);
			Particle p = new Particle();
			p.P.set((float)c.re(),(float)c.im(),0);
			pList.add(p);
			pSides.add(0.0f);
		}
	}
	
	// get weighted average of points
	public Vec getPointCenter() {
		Vec v = new Vec(0,0,0);
		for (Particle p: pList)
			v.addDirect(p.P);
		return v.mul(1.0f/(float)pList.size());
	}
	
	public Vec getRealPos(Particle p) {
		return p.P.mul(PythCal.cont.scale).add(PythCal.cont.localCenter);
	}

	public void setupPaintsCamera() {
		paintArc.setColor(Color.LTGRAY);
		paintText.setColor(Color.WHITE);

		paintSideText.setColor(Color.YELLOW);

		paintAngleText.setColor(Color.MAGENTA);
	}

	
	public void setupPaints() {
		paintLine.setColor(Color.RED);
		paintLine.setStrokeWidth(2);
		paintLine.setAntiAlias(true);

		paintArc.setColor(Color.DKGRAY);
		paintArc.setStrokeWidth(1.5f);
		paintArc.setAntiAlias(true);
		paintArc.setStyle(Paint.Style.STROKE);
		
		paintCorner.setColor(Color.BLUE);
		paintCorner.setAntiAlias(true);

		paintText.setColor(Color.BLACK);
		paintText.setStrokeWidth(2);
		paintText.setTextSize(PythCal.cont.textSize);
		paintText.setAntiAlias(true);

		paintSideText.setColor(Color.BLACK);
		paintSideText.setStrokeWidth(1);
		paintSideText.setTextSize(PythCal.cont.textSize*0.9f);
		paintSideText.setAntiAlias(true);

		paintAngleText.setColor(Color.MAGENTA);
		paintAngleText.setStrokeWidth(1);
		paintAngleText.setTextSize(PythCal.cont.textSize*0.7f);
		paintAngleText.setAntiAlias(true);
	}
	
	float getMaxAngle() {
		float max = -1;
		for (Particle p: pList)
			if (p.angle>max)
				max = p.angle;
		return max;
	}
	
	@SuppressWarnings("unchecked")
	void render(Canvas canvas, Vec cen, float scale, float circleSize, Vec bottom) {

		// First sort all points by radians
		Collections.sort(pList);

		// Calculate the arcs and starting angles
		calculateArcs();
		
		drawLines(canvas);
		drawPoints(canvas);
		drawArcs(canvas);
		drawPointText(canvas);
		
		if (Container.settings[Container.DRAW_SIDES])
			drawSideText(canvas);
		if (Container.settings[Container.DRAW_ANGLES])
			drawAngleText(canvas);
		if (Container.settings[Container.DRAW_BOTTOMTEXT])
			drawBottomText(canvas, bottom);
	}

	
	private void calculateArcs() {
		
		Vec v2 = new Vec(1,0,0);
		
		for (int i=0;i<pList.size();i++) {
			findNeighbourParticles(i);
			
			Vec v0 = PythCal.cont.p1.P.sub(PythCal.cont.p0.P).norm();
			Vec v1 = PythCal.cont.p2.P.sub(PythCal.cont.p0.P).norm();
			
			float ang = (float)(Math.acos(v0.dot(v1))*PythCal.cont.convRad);
			float angStart = (float)(Math.acos(v1.dot(v2))*PythCal.cont.convRad);
			if (PythCal.cont.p2.P.y>PythCal.cont.p0.P.y) 
				angStart = -angStart;
			
			pList.get(i).angle=ang;
			pList.get(i).angleStart =  -angStart;
		}		

	}
		
		
	
	
	private void drawLines(Canvas canvas) {
		for (int i=0;i<pList.size();i++) {
			findNeighbourParticles(i);

			Vec v1 = getRealPos(PythCal.cont.p0);
			Vec v2 = getRealPos(PythCal.cont.p1);

			pSides.set(i, (PythCal.cont.p0.P.sub(PythCal.cont.p1.P).len()));
			
			canvas.drawLine(v1.x,v1.y,v2.x,v2.y, paintLine );
		}		

	}
	
	private void drawPoints(Canvas canvas) {
		for (Particle p : pList) {
			Vec v = getRealPos(p);
			canvas.drawCircle(v.x, v.y, PythCal.cont.circleSize, paintCorner);
		}
	
	}

	private void drawArcs(Canvas canvas) {
		float s = PythCal.cont.circleSize*2;
		for (Particle p : pList) {
			Vec v = getRealPos(p);
			RectF oval = new RectF(v.x-s, v.y-s, v.x+s, v.y+s);
			canvas.drawArc(oval, p.angleStart, p.angle , true, paintArc);
		}
	
	}

	private void drawPointText(Canvas canvas) {
		char c = 'A';
		for (Particle p : pList) {
			Vec v = getRealPos(p);
			v = v.sub(PythCal.cont.localCenter).mul(PythCal.cont.pointTextScale).add(PythCal.cont.localCenter);
			String txt = "" + c;
			canvas.drawText(txt, v.x-PythCal.cont.textSize/2, v.y+PythCal.cont.textSize/2, paintText);
			c++;
		}
			
	}

	private void drawAngleText(Canvas canvas) {
		DecimalFormat dec = new DecimalFormat("###");
		if (Container.settings[Container.DRAW_RADIANS])
			dec = new DecimalFormat("#.##");
	
		for (Particle p: pList) {
			Complex c = Complex.polar(40, (p.angleStart+p.angle/2.0)/PythCal.cont.convRad);
			Vec v = getRealPos(p);
			float angle = p.angle;
			if (Container.settings[Container.DRAW_RADIANS])
				angle/=PythCal.cont.convRad;
			String txt = dec.format(angle);
			if (!Container.settings[Container.DRAW_RADIANS])
				txt+=PythCal.cont.degree;
			canvas.drawText(txt, v.x-PythCal.cont.textSize/2+(int)c.re(), v.y+PythCal.cont.textSize/3+(int)c.im(), paintAngleText);
		}
			
	}

	private void drawSideText(Canvas canvas) {
		for (int i=0;i<pList.size();i++) {
			DecimalFormat dec = new DecimalFormat("###.###");
			findNeighbourParticles(i);
			
		
			Vec v1 = getRealPos(PythCal.cont.p0);
			Vec v2 = getRealPos(PythCal.cont.p1);

			v1 = v1.sub(PythCal.cont.localCenter).mul(1.0f).add(PythCal.cont.localCenter);
			v2= v2.sub(PythCal.cont.localCenter).mul(1.0f).add(PythCal.cont.localCenter);

			Vec v = v1.add(v2).mul(0.5f);
			String txt = dec.format(pSides.get(i)*PythCal.cont.visualScale);
			canvas.drawText(txt, v.x, v.y, paintSideText);
		}

	
	}

	private void drawBottomText(Canvas canvas, Vec pos) {
		DecimalFormat dec = new DecimalFormat("###.##");
		DecimalFormat decAng = new DecimalFormat("###");
		float dx = PythCal.cont.windowWidth / pList.size();
		float dy = PythCal.cont.textYspacing;
		char c = 'A';
			for (int i=0;i<pList.size();i++) {
			Vec p = pos.add(new Vec(i*dx + dx/2.5f,0,0));
			String txt = dec.format(pSides.get(i)*PythCal.cont.visualScale);
			canvas.drawText("" + c, p.x, p.y, paintText);
			canvas.drawText(txt, p.x, p.y+ dy, paintSideText);
			canvas.drawText("" + decAng.format(pList.get(i).angle) + PythCal.cont.degree, p.x, p.y+2*dy, paintAngleText);
			c++;
		}

	
	}

    public void findNeighbourParticles(int i) {
    	PythCal.cont.p0 = pList.get(i);
		int j=i+1;
		if (j==pList.size()) j=0;
		PythCal.cont.p1 = pList.get(j);
		int k=i-1;
		if (k<0) k=pList.size()-1;
		PythCal.cont.p2 = pList.get(k);
    }

	
}
